-- Copyright (c) 2015,2016 Lucky Byte, Inc.
--
-- Summary : ACP 特殊的功能模块
--
-- Author  : 吴小虎 <xiaohu@lucky-byte.com>
-- Since   : 2016.4.29
--
-- History
--  * 2015.5.6 : 创建此文件
--

require 'core.p071.trinfo'
require 'core.p071.syscode'

-- 新建报文
lib071.new_packet = function()
    local _packet = lib071._new_packet()

    -- 设置常数域
    _packet.set('version', '5.0.0')
    _packet.set('encoding', 'UTF-8')
    _packet.set('signMethod', '01')
    _packet.set('currencyCode', '156')
    return _packet
end


-- 对报文进行签名
lib071.sign = function(packet, merch)
    assert(packet._class == 'Packet071', string.format(
        'lib071.sign() 需要 Packet071 报文，当前报文类型为[%s]', packet._class))

    -- 商户签名密钥采用固定命名规则
    local _merno = merch.get('merno')
    if not lib071._sign(packet, _merno) then
        return '01'
    end
    return '00'
end


-- 计算手续费
--
_calc_fee = function(merch, packet, trinfo)
    logger.fatal('不能计算全渠道手续费.')
    return nil
end


-- 判定借贷记标志
local _get_dcflag = function(trinfo, reqpkt)
    if not trinfo.settl then
        logger.debug('非清算类交易无需判定卡借贷记标志.')
        return nil
    end
    local _pri_acct = reqpkt.get('accNo')
    if string.trimlen(_pri_acct) == 0 then
        logger.info('判定借贷记卡错误[报文中无账号字段].')
        return nil
    end
    local _bininfo = core.cardbin.query(_pri_acct)
    if not _bininfo then
        return 99
    end
    return _bininfo.get('debit_credit_flag') == 1 and 1 or 2
end


-- 通过 银联ACP 渠道转发请求报文
--
lib071.forward = function(args)
    assert(args.packet._class == 'Packet071', string.format(
        'lib071.forward() 需要 Packet071 报文，当前报文类型为[%s]', args.packet._class))

    if not args.merch then
        logger.warn('转发 071 报文未提供商户信息.')
        return nil
    end

    -- 交易流水 UUID
    if not args.uuid then
        logger.warn('转发 071 报文时未提供交易流水 UUID.')
        args.uuid = uuid()
    end

    -- 如果没有提供交易信息，则查询交易信息
    if not args.trinfo then args.trinfo = lib071.trinfo(args.packet) end

    -- 重组模式下需要检查交易权限
    if args.indirect then
        if args.trinfo.trctl then
            local _tramt = args.packet.get('txnAmt')
            if string.trimlen(_tramt) > 0 then
                _tramt = tonumber(_tramt) / 100
            else
                _tramt = nil
            end
            local _rescode = core.trctl.check({
                merch = args.merch, trinfo = args.trinfo, tramt = _tramt
            })
            if _rescode ~= '00' then
                logger.error('商户[%s]配置的交易控制不允许继续转发当前的交易...',
                    args.merch and args.merch.get('merno') or '')
                return {
                    respkt  = lib071.respkt(args.packet, _rescode),
                    rescode = _rescode
                }
            end
            logger.debug('交易控制检测通过，继续转发此交易...')
        end
    end

    -- 执行转发，转发前报文需要进行编码处理
    local _encoded_pkt = lib071.encode(args.packet)
    local _fowd = lib071._forward(_encoded_pkt, args.indirect)

    -- 补充流水信息，下面这些字段是在报文编码时由 java 代码设置
    for _, k in ipairs {
        'certId', 'signMethod', 'encryptCertId', 'backUrl', 'channelType'
    } do
        args.packet.set(k, _encoded_pkt.get(k) or '')
    end

    -- 记录转发交易流水
    local _trans_record = {
        uuid       = args.uuid,
        incoming   = false,
        chnl       = 3,
        indirect   = args.indirect,
        trinfo     = core.json.encode(args.trinfo),
        i_pkt      = args.packet.tojson(),
    }
    -- 登记流水中的商户信息
    _trans_record.merch = args.merch.tojson()

    if _fowd then
        _trans_record.netinfo = _fowd.netinfo   -- 接出渠道网络通讯信息
        if _fowd.respkt then                    -- 接出渠道返回报文信息
            _trans_record.o_pkt = _fowd.respkt.tojson()
            _trans_record.status = 0
            local _code, _desc = lib071.rescode(_fowd.respkt)
            _trans_record.notes = _code and _code .. '：' .. _desc or '无响应码'

            _trans_record.dcflag = _get_dcflag(args.trinfo, args.packet)

            -- 如果交易成功，则计算手续费
            if lib071.respkt_ok(_fowd.respkt) then
                if args.trinfo.hasfee then
                    _trans_record.fee =
                        _calc_fee(args.merch, _fowd.respkt, args.trinfo)
                end
            end
        else
            _trans_record.status = 1
            _trans_record.notes = '未收到有效响应报文，请查看日志'
        end
    end
    if jdbc.upsert('pay_trlist', _trans_record) < 0 then
        logger.error('记录转发交易[%s]的流水失败.', args.uuid)
    end
    _fowd.trans_record = _trans_record
    return _fowd
end


-- 规范应答码表
local _acp_rescode_t = require "core.rscode.acp"

-- 创建响应报文
--
-- 参数 rescode 为平台应答码
--
lib071.respkt = function(packet, sys_rescode)
    assert(packet._class == 'Packet071', string.format(
        'lib071.respkt() 需要 Packet071 报文，当前报文类型为[%s]', packet._class))

    -- 映射为标准错误码
    local _acp_rescode = lib071.sys_rescode_t[sys_rescode]
    if not _acp_rescode then
        logger.fatal('系统响应码[%s]不存在.', sys_rescode)
        _acp_rescode = '99'
    end

    local _respkt = lib071.new_packet()

    _respkt.set('respCode', _acp_rescode)
    _respkt.set('respMsg',  _acp_rescode_t[_acp_rescode])
    return _respkt
end


-- 获取报文中的应答码及对应的文字描述
--
lib071.rescode = function(packet)
    if not packet then return '' end

    assert(packet._class == 'Packet071', string.format(
        'lib071.rescode() 需要 Packet071 报文，当前报文类型为[%s]', packet._class))

    local _acp_rescode = packet.get('respCode')
    local _acp_resmsg  = packet.get('respMsg') or '未知错误'
    return _acp_rescode, _acp_resmsg
end


-- 判断报文应答码是否表示成功
lib071.respkt_ok = function(packet)
    assert(packet._class == 'Packet071', string.format(
        'lib071.respkt_ok() 需要 Packet071 报文，当前报文类型为[%s]', packet._class))

    return packet.get('respCode') == '00'
end
